package com.gpt.article.service.impl.taskHandle;

import chatgpt.ChatGPT;
import com.gpt.article.domain.*;
import com.gpt.article.mapper.GptSpiderArticleMapper;
import com.gpt.article.service.impl.taskHandle.task.GenQContentTasker;
import com.gpt.article.service.impl.taskHandle.task.XiGaoTasker;
import com.ruoyi.common.config.RuoYiConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

public class GenTask {
    @Autowired
    GptSpiderArticleMapper gptSpiderArticleMapper;
    private static Logger logger = LoggerFactory.getLogger(GenTask.class);
    // thread
    private int threadCount = 1;                                                    // 洗稿线程数量
    private ExecutorService xigaos = Executors.newCachedThreadPool();                // 洗稿线程池
    private List<XigaoThread> xigaoThreads = new CopyOnWriteArrayList<XigaoThread>();     // 洗稿线程引用镜像
    private volatile RunGenData runData = new RunDataImpl();

    private ChatGPT chatGPT;

    private GenTask task;

    private Integer taskNum = 0;

    private Integer modelNum = 0;

    private Integer xiGaoNum = 0;

    private Long taskId;

    private Integer oneToNum;

    private Integer txtlength;

    private Boolean tuswitch;

    private Boolean xituSwitch;

    private String useModel;
    //生成类型
    private String gentype;

    //关键词/关键参数
    private String keysWord;

    //参考
    private String refer;

    //操作用户
    private String acc;
    //执行参数
    private  Map<String,Object> psMap;


    //提示词角色详细参数配置
    private GptFunPrompts gptFunPrompts;

    public String getRefer() {
        return refer;
    }

    public void setRefer(String refer) {
        this.refer = refer;
    }

    public String getAcc() {
        return acc;
    }

    public void setAcc(String acc) {
        this.acc = acc;
    }

    public Map<String, Object> getPsMap() {
        return psMap;
    }

    public void setPsMap(Map<String, Object> psMap) {
        this.psMap = psMap;
    }

    public Integer getModelNum() {
        return modelNum;
    }

    public void setModelNum(Integer modelNum) {
        this.modelNum = modelNum;
    }


    public static class Builder {

        private GenTask task = new GenTask();

        /**
         * 添加洗稿
         * @param gptSpiderArticleList
         * @return
         */
        public Builder addArticleList(List<GptSpiderArticle> gptSpiderArticleList){
            for(GptSpiderArticle gptSpiderArticle:gptSpiderArticleList){
                task.getRunData().addTask(gptSpiderArticle);
            }
            logger.info(">>>>>>>>>>> 添加任务队列成功,数量："+gptSpiderArticleList.size());
            return this;
        }

        //添加任务，此用Integer类型数字代替，便于后续作为任务编号扩展
        public Builder addTaskNo(List<Integer> taskNos){
            for(Integer in:taskNos){
                task.getRunData().addTask(in);
            }
            logger.info(">>>>>>>>>>> 添加任务队列成功,数量："+taskNos.size());
            return this;
        }

        //添加各大模型比较器
        public Builder addQContentTask(List<QContent> qContents){
            System.out.println("加载任务重.."+qContents.size());
            for(QContent li:qContents){
                task.getRunData().addTask(li);
            }
            logger.info(">>>>>>>>>>> 添加任务队列成功,数量："+qContents.size());
            return this;
        }

        //添加主题生成任务
        public Builder addTopicTask(List<GptTopicTitle> gptTopicTitles){
            for(GptTopicTitle li:gptTopicTitles){
                task.getRunData().addTask(li);
            }
            logger.info(">>>>>>>>>>> 添加任务队列成功,数量："+gptTopicTitles.size());
            return this;
        }



        //添加内容生成分类任务
        public Builder addTxtClassifiesTask(List<TxtClassify> txtClassifies){
            for(TxtClassify li:txtClassifies){
                task.getRunData().addTask(li);
            }
            logger.info(">>>>>>>>>>> 添加任务队列成功,数量："+txtClassifies.size());
            return this;
        }

        //添加参数
        public Builder addPsMap(Map<String,Object> psmap){
            task.psMap = psmap;
            return this;
        }
//        chatGPT
        public Builder setchatGpt(ChatGPT chatGPT){
            task.chatGPT = chatGPT;
            return this;
        }

        public Builder setGenType(String gentype){
            task.gentype = gentype;
            return this;
        }
        public Builder setAcc(String acc){
            task.acc = acc;
            return this;
        }
        public Builder setKeysWord(String keysWord){
            task.keysWord = keysWord;
            return this;
        }


        /**
         * 必须调用是放在第一位 ，用于判断任务数量和线程的分配问题
         * @param taskNum
         * @return
         */
        public  Builder setTaskNum(Integer taskNum) {
            task.taskNum = taskNum;
            return this;
        }

        public Builder setModelNum(Integer modelNum ){
            task.modelNum = modelNum;
            return this;
        }

        public Builder setOneToNum(Integer oneToNum ){
            task.oneToNum = oneToNum;
            return this;
        }
        public Builder setUseModel(String useModel ){
            task.useModel = useModel;
            return this;
        }

        public Builder setGptFunPrompts(GptFunPrompts gptFunPrompts){
            task.gptFunPrompts = gptFunPrompts;
            return this;
        }

        //参考语句
        public Builder setRefer(String refer){
            task.refer = refer;
            return this;
        }


        public Builder setTxtlength(Integer txtlength ){
            task.txtlength = txtlength;
            return this;
        }

        public Builder setTuswitch(Boolean tuswitch ){
            task.tuswitch = tuswitch;
            return this;
        }

        public Builder setXituSwitch(Boolean xituSwitch ){
            task.xituSwitch = xituSwitch;
            return this;
        }

        /**
         * 洗稿并发线程数
         *
         * @param threadCount
         * @return Builder
         */
        public Builder setThreadCount(int threadCount) {

            //线程数逻辑 ，任务数量低于
            Integer taskn = task.getTaskNum();
            int threadNum = taskn<threadCount?taskn:threadCount;
            task.threadCount = threadNum;
            return this;
        }
        public GenTask build() {
            return task;
        }

    }

    /**
     * 洗稿启动
     *
     * @param sync  true=同步方式、false=异步方式
     */
    public void start(boolean sync,String type){
        //审查
        if(!"title".equals(type)){
            if (runData == null) {
                if("qaContent".equals(type)){
                    new GenQContentTasker().seedTxt(0,0,"end","任务数量有误");
                }
                throw new RuntimeException("任务不能为空.....");
            }
            if (runData.getGptNum() <= 0) {
                if("qaContent".equals(type)){
                    new GenQContentTasker().seedTxt(0,0,"end","任务数量有误");
                }
                throw new RuntimeException("任务数量不能为空....");
            }
        }

        if (threadCount<1 || threadCount>1000) {
            if("qaContent".equals(type)){
                new GenQContentTasker().seedTxt(0,0,"end","任务数量有误");
            }
            throw new RuntimeException("threadCount invalid, threadCount : " + threadCount);
        }

        logger.info(">>>>>>>>>>> 任务开始 ...");
        for (int i = 0; i < threadCount; i++) {
            XigaoThread xigaoerThread = new XigaoThread(this,chatGPT,taskId);
            xigaoThreads.add(xigaoerThread);
        }
        for (XigaoThread xigaoerThread: xigaoThreads) {
            xigaos.execute(xigaoerThread);
        }
        xigaos.shutdown();
        int threadCount = ((ThreadPoolExecutor)xigaos).getActiveCount();
        logger.info("当前线程数："+threadCount);
        if (sync) {
            try {
                while (!xigaos.awaitTermination(5, TimeUnit.SECONDS)) {
                    logger.info(">>>>>>>>>>> Task running ...");
                }
            } catch (InterruptedException e) {
                logger.error(e.getMessage(), e);

            }
        }

    }



    public RunGenData getRunData() {
        return runData;
    }

    /**
     * 洗稿任务创建
     * @param articles
     * @return
     */
    public Integer createXigao(List<GptSpiderArticle> articles, Long taskId, Map<String,Object> genPsmap){
        this.taskId = taskId;
        Integer oneToNum = Integer.valueOf(String.valueOf(genPsmap.get("oneToNum")));
        Integer txtlength = Integer.valueOf(String.valueOf(genPsmap.get("txtlength")));
        Boolean tuswitch = Boolean.valueOf(String.valueOf(genPsmap.get("tuswitch")));
        Boolean xituSwitch = Boolean.valueOf(String.valueOf(genPsmap.get("xituSwitch")));
        String useModel = String.valueOf(genPsmap.get("useModel"));
        int genNum = oneToNum*articles.size();
        chatGPT = ChatGPT.builder()
                .apiKey(RuoYiConfig.getApiKeys())
                .timeout(900)
//                .proxy(proxy)
                .apiHost(RuoYiConfig.getGptApiHost()) //代理地址
                .build()
                .init();

         task = new GenTask.Builder()
                 .setTaskNum(genNum)
                .setThreadCount(Integer.valueOf(RuoYiConfig.getGenThreadCount()))
                .addArticleList(articles)
                .setchatGpt(chatGPT)
                .setOneToNum(oneToNum)
                .setUseModel(useModel)
                .setTxtlength(txtlength)
                .setTuswitch(tuswitch)
                .setXituSwitch(xituSwitch)
                .build();
        task.start(false,"xigao");
        logger.info("洗稿任务结束：{}",articles.size());

        new XiGaoTasker().upTask(taskId,0,0,0,"2");
//        WebSocketUsers.sendMessageToUsersByText("end");
        return  articles.size();
    }



    /**
     * 根据要求生成主题内容任务创建
     * @param genPsmap
     * @return
     */
    public Integer createContentByKeyWors( Long taskId, Map<String,Object> genPsmap,GptFunPrompts gptFunPrompts,String acc){
        this.taskId = taskId;
        Integer oneToNum = Integer.valueOf(String.valueOf(genPsmap.get("oneToNum")));
        String keyWords = String.valueOf(genPsmap.get("keyWords"));
        String refer = String.valueOf(genPsmap.get("refer"));
        String useModel = gptFunPrompts.getUseModel();

        //分解任务
        //每个线程生成 50个
        int initNum = 50;
        //任务数
        int taskNum = 0;
        if(oneToNum>initNum){
            taskNum = oneToNum/initNum;
            if(oneToNum%initNum>0){
                taskNum +=1 ;
            }
        }else{
            taskNum = 1;
        }
        ArrayList<Integer> taskNamelist = new ArrayList<Integer>();
        for (int i = 1; i <= taskNum; i++) {
            taskNamelist.add(i);
        }


        int genNum = oneToNum;
        chatGPT = ChatGPT.builder()
                .apiKey(RuoYiConfig.getApiKeys())
                .timeout(900)
//                .proxy(proxy)
                .apiHost(RuoYiConfig.getGptApiHost()) //代理地址
                .build()
                .init();

        task = new GenTask.Builder()
                .setTaskNum(genNum)
                .setAcc(acc)
                .setThreadCount(Integer.valueOf(RuoYiConfig.getGenThreadCount()))
                .setGenType("title")
                .setKeysWord(keyWords)
                .setGptFunPrompts(gptFunPrompts)
                .setRefer(refer)
//                .addArticleList(articles)
                .setchatGpt(chatGPT)
                .setOneToNum(oneToNum)
                .setUseModel(useModel)
                .addTaskNo(taskNamelist)
//                .setTxtlength(txtlength)
//                .setTuswitch(tuswitch)
//                .setXituSwitch(xituSwitch)
                .build();


        task.start(false,"title");
//        logger.info("文案创建任务结束：{}");

        new XiGaoTasker().upTask(taskId,0,0,genNum,"2");
//        WebSocketUsers.sendMessageToUsersByText("end");
        return  genNum;
    }



    /**
     * 查询是否洗稿
     * @param id
     * @return
     */
    public Boolean hasXigao(Long id){
        GptSpiderArticle gptSpiderArticle  = gptSpiderArticleMapper.selectGptSpiderArticleById(id);
        String status =  gptSpiderArticle.getStatus();
        if("0".equals(status)){
            //未洗稿
            return false;
        }else{
            return true;
        }
    }

    /**
     * 尝试终止
     */
    public void tryFinish(){
        boolean isRunning = false;
        for (XigaoThread xigaoThread: xigaoThreads) {
//            System.out.println(xigaoThread.isRunning()+"--xigaoThread.isRunning()");
            if (xigaoThread.isRunning()) {
                isRunning = true;
                break;
            }
        }
//        System.out.println(runData.getGptNum());
//        System.out.println(!isRunning);
        boolean isEnd = runData.getGptNum()==0 && !isRunning;
        if (isEnd) {
            logger.info("线程结束......");
            stop();
        }
    }

    /**
     * 终止
     */
    public void stop(){
        for (XigaoThread xigaoThread: xigaoThreads) {
            xigaoThread.toStop();
        }
        xigaos.shutdownNow();
        logger.info("线程停止.");
    }





    public ChatGPT getChatGPT(){
        return chatGPT;
    }

    public Integer getTaskNum() {
        return taskNum;
    }

    public Integer getXiGaoNum() {
        return xiGaoNum;
    }

    public void setXiGaoNum(Integer xiGaoNum) {
        this.xiGaoNum = xiGaoNum;
    }

    public Integer getOneToNum() {
        return oneToNum;
    }

    public void setOneToNum(Integer oneToNum) {
        this.oneToNum = oneToNum;
    }

    public Integer getTxtlength() {
        return txtlength;
    }

    public void setTxtlength(Integer txtlength) {
        this.txtlength = txtlength;
    }

    public Boolean getTuswitch() {
        return tuswitch;
    }

    public void setTuswitch(Boolean tuswitch) {
        this.tuswitch = tuswitch;
    }

    public Boolean getXituSwitch() {
        return xituSwitch;
    }

    public void setXituSwitch(Boolean xituSwitch) {
        this.xituSwitch = xituSwitch;
    }

    public String getUseModel() {
        return useModel;
    }

    public void setUseModel(String useModel) {
        this.useModel = useModel;
    }

    public String getGentype() {
        return gentype;
    }

    public void setGentype(String gentype) {
        this.gentype = gentype;
    }

    public String getKeysWord() {
        return keysWord;
    }

    public void setKeysWord(String keysWord) {
        this.keysWord = keysWord;
    }

    public GptFunPrompts getGptFunPrompts() {
        return gptFunPrompts;
    }

    public void setGptFunPrompts(GptFunPrompts gptFunPrompts) {
        this.gptFunPrompts = gptFunPrompts;
    }

}
